﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using ArgusPCLib.Mathematics.StructWrappers;
using Struct = System.Int32;

namespace ArgusPCLib.Mathematics
{
	struct StructWrapperTemplate : ILinearScalar
	{
		Struct _value;

		public StructWrapperTemplate(Struct value)
		{
			this._value = value;
		}

		public static implicit operator StructWrapperTemplate(Struct value)
		{
			return new StructWrapperTemplate(value);
		}

		public static implicit operator Struct(StructWrapperTemplate value)
		{
			return value._value;
		}

		#region IOperand
		public static StructWrapperTemplate Parse(string text, string format, IFormatProvider formatProvider)
		{
			if (typeof(Struct) != typeof(int))
				throw new Exception("Please customize the templated code...");
			NumberStyles numberStyle;
			if (format != null && format.ToLowerInvariant().StartsWith("h"))
				numberStyle = NumberStyles.HexNumber;
			else
				numberStyle = NumberStyles.Integer;
			return Struct.Parse(text, numberStyle, formatProvider);
		}

		public static bool TryParse(string text, string format, IFormatProvider formatProvider, out StructWrapperTemplate value)
		{
			if (typeof(Struct) != typeof(int))
				throw new Exception("Please customize the templated code...");
			NumberStyles numberStyle;
			if (format != null && format.ToLowerInvariant().StartsWith("h"))
				numberStyle = NumberStyles.HexNumber;
			else
				numberStyle = NumberStyles.Integer;
			Struct result;
			if (Struct.TryParse(text, numberStyle, formatProvider, out result))
			{
				value = new StructWrapperTemplate(result);
				return true;
			}
			else
			{
				value = new StructWrapperTemplate();
				return false;
			}
		}

		public static int PartialParse(string text, string format, IFormatProvider formatProvider, out StructWrapperTemplate value)
		{
			if (typeof(Struct) != typeof(int))
				throw new Exception("Please customize the templated code...");

			NumberFormatInfo nfi = (NumberFormatInfo)formatProvider;

			NumberStyles numberStyle;
			if (format != null && format.ToLowerInvariant().StartsWith("h"))
				numberStyle = NumberStyles.HexNumber;
			else
				numberStyle = NumberStyles.Integer;

			Struct result = new Struct();
			int RetVal = -1;
			int i = Algorithms.Bisection<Int32Wrapper>(new Interval<Int32Wrapper>(0, text.Length), (length) =>
			{
				if (Struct.TryParse(text.Substring(0, length), numberStyle, nfi, out result))
				{
					RetVal = length;
					return -1;
				}
				else
					return 1;
			}, 0);

			value = new StructWrapperTemplate(result);
			if (RetVal < 1)
				return -1;
			else
				return RetVal;
		}

		IOperand IOperand.GetDeepCopy() { return new StructWrapperTemplate(this._value); }
		#endregion

		#region IFormattable
		public string ToString(string format, IFormatProvider formatProvider)
		{
			return this._value.ToString(format, formatProvider);
		}

		public override string ToString()
		{
			return this.ToString(null, null);
		}
		#endregion

		#region IScalar
		public static StructWrapperTemplate Zero { get { return new StructWrapperTemplate(0); } }
		public static StructWrapperTemplate One { get { return new StructWrapperTemplate(1); } }

		public static StructWrapperTemplate operator +(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return new StructWrapperTemplate(a._value + b._value);
		}

		public static StructWrapperTemplate operator -(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return new StructWrapperTemplate(a._value - b._value);
		}

		public static StructWrapperTemplate operator *(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return new StructWrapperTemplate(a._value * b._value);
		}

		public static StructWrapperTemplate operator /(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return new StructWrapperTemplate(a._value / b._value);
		}

		public static bool operator ==(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return a._value == b._value;
		}

		public static bool operator !=(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return a._value != b._value;
		}

		IScalar IScalar.Add(IScalar value) { return this + (StructWrapperTemplate)value; }
		IScalar IScalar.Multiply(IScalar value) { return this * (StructWrapperTemplate)value; }
		IScalar IScalar.Subtract(IScalar value) { return this - (StructWrapperTemplate)value; }
		IScalar IScalar.Divide(IScalar value) { return this / (StructWrapperTemplate)value; }
		bool IScalar.IsEqualTo(IScalar value) { return this == (StructWrapperTemplate)value; }
		#endregion

		#region ILinearScalar
		public static bool operator <(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return a._value < b._value;
		}

		public static bool operator >(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return a._value > b._value;
		}

		public static bool operator <=(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return a._value <= b._value;
		}

		public static bool operator >=(StructWrapperTemplate a, StructWrapperTemplate b)
		{
			return a._value >= b._value;
		}

		bool ILinearScalar.IsGreaterThan(ILinearScalar value) { return this > (StructWrapperTemplate)value; }
		bool ILinearScalar.IsSmallerThan(ILinearScalar value) { return this < (StructWrapperTemplate)value; }
		#endregion

		#region IComparable
		int IComparable.CompareTo(object obj)
		{
			StructWrapperTemplate b = (StructWrapperTemplate)obj;
			if (this._value < b._value)
				return -1;
			if (this._value > b._value)
				return 1;
			return 0;
		}
		#endregion
	}
}
